import crypto from 'crypto';
import { binaryToBase58 } from './base58.js';

const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', {
  namedCurve:  'P-256', //'secp256k1', // invalid 'secp256r1',
  publicKeyEncoding: { type: 'spki', format: 'der' },
  privateKeyEncoding: { type: 'pkcs8', format: 'der' }
});
const pubKey = publicKey;
const pubKeyHash = getPublicKeyHash(pubKey);
console.log("privateKey:", privateKey.toString('base64'), "type:", typeof privateKey);
console.log("publicKey:", publicKey.toString('base64'), "type:", typeof publicKey);
console.log("publicKeyHash:", pubKeyHash.toString('hex'));
console.log('address:', getAddress(pubKeyHash));

const key = "42946e14cd837a75df282394ffefe17618d06e98d026446f0906b88fd331be5c:0";
const sign = crypto.createSign('SHA256');
const data = Buffer.from(key);
sign.update(data);
sign.end();
const privateKeyString = `-----BEGIN PRIVATE KEY-----\n${privateKey.toString('base64')}\n-----END PRIVATE KEY-----`;
const signature = sign.sign(privateKeyString);
console.log("key:", key, "sign:", Buffer.from(signature).toString('hex'));

const verifier = crypto.createVerify('sha256');
verifier.update(data);
verifier.end();
const l1 = "-----BEGIN PUBLIC KEY-----\n";
// Encrypted data
const l2 = publicKey.toString('base64');
// Finishing public key execution
const l3 = "\n-----END PUBLIC KEY-----";
// concatenating all public keys
const publicKeyStr = l1 + l2 + l3
const result = verifier.verify(publicKeyStr, signature);
console.log("verify result:", result);

function getPublicKeyHash(pubKey) {
  const sha256 = crypto.createHash('sha256');
  const hash256Binary = sha256.update(pubKey).digest();
  const ripemd160 = crypto.createHash('ripemd160');
  // get the public key in a compressed format 20 bytes
  const pubKeyHash = ripemd160.update(hash256Binary).digest();
  return pubKeyHash;
}

function getAddress(pubKeyHash) {
  const leaderBuffer = Buffer.from([0]);
  const hashBuffer = Buffer.from(pubKeyHash);

  const payloadBuffer = Buffer.concat([leaderBuffer, hashBuffer]);
  const checkSumBuffer = Buffer.from(checksum(payloadBuffer));
  const addressBuffer = Buffer.concat([leaderBuffer, hashBuffer, checkSumBuffer]);
  return binaryToBase58(addressBuffer);
}

function doubleHash(data) {
  const sha256 = crypto.createHash('sha256');
  const data1 = sha256.update(data).digest();
  const sha256Again = crypto.createHash('sha256');
  return sha256Again.update(data1).digest();
}

function checksum(data) {
  const doubleHashData = doubleHash(data);
  return doubleHashData.subarray(0, 4);
}
